/**
 *    Copyright (C) 2008, 2009  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_NATIVE_EXCEPTIONS_HPP
#define	_CUBEFS_CORE_NATIVE_EXCEPTIONS_HPP

#include <natives.h>
#include <cubefs/api/exceptions.hpp>

namespace cubefs{
namespace java {

using namespace cubefs::api;


class JavaException: public CubefsException {
    bool rethrow_;
public:
    JavaException(const string &source, const string &message, bool rethrow = false): CubefsException(source, message), rethrow_(rethrow) {}

    bool rethrow() {
        return rethrow_;
    }
};


bool ThrowCubefsException(JNIEnv *env, const char *source, const char *msg, BigInt data = 0);
bool ThrowDispatchException(JNIEnv *env, const char *source, const char *msg, int code1, int code2);
bool ThrowTypeCastException(JNIEnv *env, const char *source, const char *msg, const Type* src, const Type* dst);
bool ThrowNPEException(JNIEnv *env, const char *source, const char *msg);
bool ThrowBoundsException(JNIEnv *env, const char *source, const char *msg, BigInt index, BigInt index1, BigInt index2);

#define CUBEFS_EXC_BEGIN try {

#define CUBEFS_EXC_HANDLE }                                                     \
    catch (BoundsException ex) {                                                \
        ThrowBoundsException(env, ex.source().c_str(), ex.message().c_str(), ex.index(), ex.index1(), ex.index2());\
    }                                                                           \
    catch (TypeCastException ex) {                                              \
        ThrowTypeCastException(env, ex.source().c_str(), ex.message().c_str(), ex.src_type(), ex.tgt_type());\
    }                                                                           \
    catch (DispatchException ex) {                                              \
        ThrowDispatchException(env, ex.source().c_str(), ex.message().c_str(), ex.code1(), ex.code2());\
    }                                                                           \
    catch (NullPointerException ex) {                                           \
        ThrowNPEException(env, ex.source().c_str(), ex.message().c_str());      \
    }                                                                           \
    catch (JavaException ex) {                                                  \
        if (ex.rethrow())                                                       \
            ThrowCubefsException(env, ex.source().c_str(), ex.message().c_str(), ex.data());\
    }                                                                           \
    catch (CubefsException ex) {                                                \
        ThrowCubefsException(env, ex.source().c_str(), ex.message().c_str(), ex.data());   \
    }                                                                           \
    catch (std::exception ex) {                                                 \
        ThrowCubefsException(env, "", ex.what());                               \
    }                                                                           \
    catch(...) {                                                                \
        ThrowCubefsException(env, __FILE__ ":" CUBEFS_AT, "Unrecognized exception");\
    }





#define CUBEFS_EXC_TEST0()                                                      \
    if (env->ExceptionCheck()) {                                                \
        throw JavaException(CUBEFS_SOURCE, "Exception in java code or JVM");    \
    }

#define CUBEFS_EXC_TEST1(msg)                                                   \
    if (env->ExceptionCheck()) {                                                \
        throw JavaException(CUBEFS_SOURCE, msg);                                \
    }

#define CUBEFS_EXC_ASSERT(arg)                                                  \
    if (!(arg)) {                                                               \
        throw JavaException(CUBEFS_SOURCE, "Exception in java code or JVM", true);\
    }


}}

#endif //_CUBEFS_CORE_NATIVE_EXCEPTIONS_HPP